/*
 * Copyright (c) 2011 Srdjan VESIC.
 * Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; GNU Free Documentation License is available at
http://www.gnu.org/copyleft/fdl.html
*/ 
	package map.gui;
import java.awt.BorderLayout;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;

import serveur.SimulationServeur;
import tests.Scenario1;
import tests.Scenario2;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import core.voyageur.Client;

import map.Airport;
import map.PaintMap;

/**
 * Display map of airport
 *@author NOMS DES MEMBRES DU GROUPE
 *@version 1.0
 */
public class GUI extends JPanel implements ActionListener, WindowListener {

	private static final long serialVersionUID = 1L;
	static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
	/** Button load */ 
	private JButton buttonLoad;
	/** Button close */
	private JButton buttonClose;
	/** Button Scenario 1 */
	private JButton buttonScenario1;
	/** Button Scenario 2 */
	private JButton buttonScenario2;
	/** Button Start Server */
	private JButton buttonStart;
	/** Button Pause Server */
	private JButton buttonPause;
	/** Button Compute Trajet list */
	private JButton buttonTrajet;
	/** Button Create Client */
	private JButton buttonClient;
	/** Button Info Client  */
	private JButton buttonInfoClient;
	/** Our canvas for displaying the map */
	private PaintMap mc; 
	/** Label containing the name of the current map*/
	private JLabel nameOfMap; 
	/** JList liste des clients dans l'onglet clients */	
	private JList listeClients;
	/** Fenetre permettant l'ajout d'un client */
	private FenetreNewClient fenetreAddClient;
	/** Fenetre permettant l'ajout d'un trajet */
	private FenetreNewTrajet fenetreNewTrajet;
	/** Fenetre Info CLient*/
	private FenetreInfoClient fenetreInfoClient;
	/** Scenario1 */
	private Scenario1 sc1;
	/** Scenario2 */
	private Scenario2 sc2;


	/** Onglets EastPanel */
	private JTabbedPane tabbedPane;
	/** Panel title */
	private JPanel titlePanel;
	/** Panel center */
	private JPanel centerPanel;
	/** Panel for button */
	private JPanel buttonPanel;
	/** Panel east of window */
	private JPanel eastPanel;

	/** Box to display options */
	private JComboBox comboBoxDisplay; 

	/** Set of airports */
	private Hashtable<String,Airport> airports; 

	private JFileChooser fc;
	
	private SimulationServeur serveur;

	public GUI() throws Exception {
		JPanel myPanel = new JPanel(new BorderLayout());
		fc = new JFileChooser();
		// Upper part which contains the title. 
		titlePanel = new JPanel();
		// Middle of the panel, containing the map.  
		centerPanel = new JPanel();
		// Lower part which contains buttons used for loading and closing a file.
		buttonPanel = new JPanel();
		// Right part containing display. 
		eastPanel = new JPanel();
		
		//Create a server.
		serveur = new SimulationServeur();
		
		// Add components:
		JLabel currentMap = new JLabel("Curently loaded map: ");
		titlePanel.add(currentMap);
		nameOfMap = new JLabel("<none>");
		titlePanel.add(nameOfMap);

		JLabel labelInfo = new JLabel("Display options:");

		String[] options = { "Cities and Lines", "Cities only", "Cities and Clients"};

		comboBoxDisplay = new JComboBox(options);
		comboBoxDisplay.setSelectedIndex(1);
		comboBoxDisplay.setPreferredSize(new Dimension(200,50));
		
		comboBoxDisplay.addActionListener(this);
		
		
		buttonScenario1 = new JButton("Scenario 1");
		buttonScenario1.setToolTipText("Launch Scenario 1");
		buttonScenario1.setEnabled(true); 
		buttonScenario1.addActionListener(this);
		buttonScenario1.setPreferredSize(new Dimension(200,40));
		
		buttonScenario2 = new JButton("Scenario 2");
		buttonScenario2.setToolTipText("Launch Scenario 2");
		buttonScenario2.setEnabled(true); 
		buttonScenario2.addActionListener(this);
		buttonScenario2.setPreferredSize(new Dimension(200,40));
		
		buttonStart = new JButton("Start");
		buttonStart.setToolTipText("Start simulation");
		buttonStart.setEnabled(false); 
		buttonStart.addActionListener(this);
		buttonStart.setPreferredSize(new Dimension(200,40));
		
		buttonPause = new JButton("Pause");
		buttonPause.setToolTipText("Pause simulation");
		buttonPause.setEnabled(false); 
		buttonPause.addActionListener(this);
		buttonPause.setPreferredSize(new Dimension(200,40));
		
		buttonTrajet = new JButton("Nouveau trajet");
		buttonTrajet.setToolTipText("Nouveau trajet");
		buttonTrajet.setEnabled(false); 
		buttonTrajet.addActionListener(this);
		
		buttonClient = new JButton("Ajouter nouveau client");
		buttonClient.setToolTipText("Nouveau client");
		buttonClient.setEnabled(true); 
		buttonClient.addActionListener(this);
		
		buttonInfoClient = new JButton("Info client");
		buttonInfoClient.setToolTipText("Info client");
		buttonInfoClient.setEnabled(true); 
		buttonInfoClient.addActionListener(this);
			
		JPanel jPServeur = new JPanel();

		jPServeur.add(labelInfo);
		jPServeur.add(comboBoxDisplay);
		//Some empty space.
		JLabel space = new JLabel();
		space.setPreferredSize(new Dimension(200,100));
		jPServeur.add(space);
		jPServeur.add(buttonScenario1);
		jPServeur.add(buttonScenario2);
		jPServeur.add(buttonStart);
		jPServeur.add(buttonPause);
		
		JPanel jPClients = new JPanel();
		jPClients.add(buttonClient);
		listeClients = new JList(serveur.getClients().values().toArray());
		listeClients.setPreferredSize(new Dimension(200, 400));
		jPClients.add(listeClients);
		jPClients.add(buttonInfoClient);

		
		JPanel jPTrajets = new JPanel();
		jPTrajets.add(buttonTrajet);
			
		tabbedPane = new JTabbedPane();
		tabbedPane.setPreferredSize(new Dimension(250,600));
		tabbedPane.addTab("Serveur", jPServeur);
		tabbedPane.addTab("Clients", jPClients);
		tabbedPane.addTab("Trajets", jPTrajets);
		
		
		eastPanel.add(tabbedPane);
		
		buttonLoad = new JButton("Load...");
		buttonLoad.setToolTipText("Load a map from a file.");
		buttonLoad.addActionListener(this);

		buttonClose = new JButton("Close");
		buttonClose.setToolTipText("Close current map.");
		buttonClose.setEnabled(true); // Change to false after
		buttonClose.addActionListener(this);


		buttonPanel.add(buttonLoad);
		buttonPanel.add(buttonClose);

		// Create an empty set of airports.
		airports = new Hashtable<String, Airport>();
				
		// Create a canvas.
		mc = new PaintMap(serveur);	
		mc.setDisplayFlights(false);
		mc.setDisplayLignes(false);
		mc.setDisplayFlights(true);
		mc.setDisplayClients(false);
		
		//Donne la paintmap au serveur pour pouvoire refresh à chaque tic d'hologe
		serveur.setMap(mc);

		// The map has dimensions 600 x 600 pixels.
		mc.setSize(600, 600);

		// Add the map to the central panel.
		centerPanel.add(mc);

		myPanel.add(titlePanel, BorderLayout.NORTH);
		myPanel.add(centerPanel, BorderLayout.CENTER);
		myPanel.add(buttonPanel, BorderLayout.SOUTH);
		myPanel.add(eastPanel, BorderLayout.EAST);

		add(myPanel);
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals(buttonLoad.getActionCommand())) {
			// The following code is executed when and only when button "Load" is clicked:

			// Open the file:
			int returnVal = fc.showOpenDialog(GUI.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				String fileName = file.toString();

				// Read the file and update the list of cities (in the object mc).
				mc.updateCitiesFromFile(fileName);

				// Repaint the map.
				mc.repaint();

				// Update the name of the map.
				nameOfMap.setText(fileName);

				// Enable / disable buttons.
				buttonClose.setEnabled(true);
				buttonLoad.setEnabled(false);
				buttonScenario1.setEnabled(true);
				buttonStart.setEnabled(true);
				buttonTrajet.setEnabled(true);
			} 
		}

		if (e.getActionCommand().equals(buttonClose.getActionCommand())) {
			// The following code is executed when and only when button "Close" is clicked:
			// Delete all airports and repaint the canvas:
			airports = new Hashtable<String, Airport>();
			mc.updateCitiesAirportList(airports);
			mc.repaint();

			// Update map name.
			nameOfMap.setText("<none>");

			// Enable / disable buttons.
			buttonClose.setEnabled(false);
			buttonLoad.setEnabled(true);
			buttonScenario1.setEnabled(true);
			buttonStart.setEnabled(false);
			buttonPause.setEnabled(false);
			buttonTrajet.setEnabled(false);
			serveur.stop();
		}
		
		if(e.getActionCommand().equals(comboBoxDisplay.getActionCommand())) {
			if(comboBoxDisplay.getSelectedItem().toString().equals("Cities and Lines")) {
				mc.setDisplayLignes(true);
				mc.setDisplayFlights(false);
				mc.setDisplayClients(false);
			} else if (comboBoxDisplay.getSelectedItem().toString().equals("Cities and Clients")){
				mc.setDisplayFlights(false);
				mc.setDisplayLignes(false);
				mc.setDisplayClients(true);
			} else {
				mc.setDisplayLignes(false);
				mc.setDisplayFlights(true);
				mc.setDisplayClients(false);
			}
			mc.repaint();
		}
		
		if(e.getActionCommand().equals(buttonScenario1.getActionCommand())) {
			if(buttonScenario1.getText().equals("Scenario 1")) {
				if(sc2 != null || serveur.isRunning()) JOptionPane.showMessageDialog(this, "Une instance de serveur est déjà en fonctionnement, vous ne pouvez pas lancer ce scénario.");
				else {
					serveur.stop();
					sc1 = new Scenario1(mc);
					sc1.start();
					buttonStart.setEnabled(false);
					buttonScenario1.setText("Stop");
					listeClients.setListData(sc1.getServeur1().getClients().values().toArray());
					buttonLoad.setEnabled(false);
				}
			} else {
				sc1.stop();
				mc.repaint();
				buttonScenario1.setText("Scenario 1");
				sc1 = null;
				listeClients.setListData(serveur.getClients().values().toArray());
				mc.repaint();
				mc.setServeur(serveur);
				if(!serveur.getAeroports().isEmpty()) buttonStart.setEnabled(true);
				buttonLoad.setEnabled(true);
			}
		}
		
		if(e.getActionCommand().equals(buttonScenario2.getActionCommand())) {
			if(buttonScenario2.getText().equals("Scenario 2")) {
				if(sc1 != null || serveur.isRunning()) JOptionPane.showMessageDialog(this, "Une instance de serveur est déjà en fonctionnement, vous ne pouvez pas lancer ce scénario.");
				else {
					serveur.stop();
					sc2 = new Scenario2(mc);
					sc2.start();
					buttonStart.setEnabled(false);
					buttonScenario2.setText("Stop");
					buttonTrajet.setEnabled(true);
					listeClients.removeAll();
					listeClients.setListData(sc2.getServeur2().getClients().values().toArray());
					buttonLoad.setEnabled(false);
				}
			} else {
				sc2.stop();
				mc.repaint();
				buttonScenario2.setText("Scenario 2");
				buttonTrajet.setEnabled(false);
				sc2 = null;
				mc.repaint();
				mc.setServeur(serveur);
				listeClients.setListData(serveur.getClients().values().toArray());
				if(!serveur.getAeroports().isEmpty()) buttonStart.setEnabled(true);
				buttonLoad.setEnabled(true);
			}
		}
		
		if(e.getActionCommand().equals(buttonStart.getActionCommand())) {
			if(sc2 != null || sc1 != null) JOptionPane.showMessageDialog(this, "Un scénario est déjà en fonctionnement, vous ne pouvez pas lancer ce scénario.");
			else {
				if(!serveur.isRunning()) {
					serveur.setRunning(true);
					buttonStart.setText("Stop");
					buttonPause.setEnabled(true);
					new Thread(serveur).start();
				} else {
					serveur.pause();
					if(JOptionPane.showConfirmDialog(this, "Vous êtes sur le point de stoper le serveur, ceci détruira tout modification effectuée depuis son lancement.\nVoulez-vous stoppez le serveur ?", "Attention !", JOptionPane.WARNING_MESSAGE, JOptionPane.WARNING_MESSAGE) == 0) {
						serveur.stop();
						buttonStart.setText("Start");
						buttonPause.setText("Pause");
						buttonPause.setEnabled(false);
						mc.repaint();
					} else serveur.resume();
				}
			}
			
		}
		
		if(e.getActionCommand().equals(buttonPause.getActionCommand())) {
			if(serveur.isPause()) {
				serveur.resume();
				buttonPause.setText("Pause");
			}
			else {
				serveur.pause();
				buttonPause.setText("Continuer");
			}
		}
		
		if(e.getActionCommand().equals(buttonTrajet.getActionCommand())) {
			if(sc2 != null)  fenetreNewTrajet = new FenetreNewTrajet(sc2.getServeur2());
			else if(sc1 != null) fenetreNewTrajet = new FenetreNewTrajet(sc1.getServeur1());
			else fenetreNewTrajet = new FenetreNewTrajet(serveur);	
			fenetreNewTrajet.addWindowListener(this);
		}
		
		if(e.getActionCommand().equals(buttonClient.getActionCommand())) {
			fenetreAddClient = new FenetreNewClient("Nouveau Client", 600, 350, serveur);
			fenetreAddClient.addWindowListener(this);					
		}
		
		if(e.getActionCommand().equals(buttonInfoClient.getActionCommand())) {
			if(listeClients.getSelectedValue() != null) {
				fenetreInfoClient = new FenetreInfoClient((Client)listeClients.getSelectedValue(), serveur.getClientsSuivis().contains((Client)listeClients.getSelectedValue()));
				fenetreInfoClient.addWindowListener(this);
			}
		}
	} // end of function actionPerformed()

	/** Creates and sets up the window. */
	static private void createAndShowGUI() throws Exception {        
		JFrame frame = new JFrame("Map");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);

		//Create and set up the content pane.
		GUI newContentPane = new GUI();
		newContentPane.setOpaque(true); 
		frame.setContentPane(newContentPane);

		frame.setLocation(100, 10);

		//Display the window.
		frame.pack();
		frame.setVisible(true);
	}

	public static void main(String[] args) throws Exception {
		createAndShowGUI();
	}
	

	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		if (arg0.getSource().equals(fenetreAddClient) || arg0.getSource().equals(fenetreNewTrajet)) {
			if(sc2 != null) listeClients.setListData(sc2.getServeur2().getClients().values().toArray());
			else if(sc1 != null) listeClients.setListData(sc1.getServeur1().getClients().values().toArray());
			else listeClients.setListData(serveur.getClients().values().toArray());
			listeClients.validate();
		}
		if (arg0.getSource().equals(fenetreInfoClient)) {
			if(fenetreInfoClient.isSuivi()) serveur.getClientsSuivis().add(fenetreInfoClient.getClient());
			else serveur.getClientsSuivis().remove(fenetreInfoClient.getClient());
		}
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}



